import { removeToken, setToken } from '@/utils/auth'
import { defineStore } from 'pinia'
import { RouteRecordRaw } from 'vue-router'
import { usePermissionStore } from './permission'
import { getToken } from '@/utils/auth'
import { router } from '@/router'
import { store } from '../index'
import {
  fetchRouterListService,
  fetchUserInfoService,
  LoginService,
  logOutService
} from '@/service'

interface RoleInfo {
  roleName: string
  value: string
}

interface UserInfo {
  userId: string | number
  username: string
  realName: string
  avatar: string
  desc?: string
  homePath?: string
  roles: RoleInfo[]
  permissions: string[]
}
interface SysState {
  userInfo: Nullable<UserInfo>
  token?: string
  roleList: []
  sessionTimeout?: boolean
  lastUpdateTime: number
  permissions: string[]
}
export const useSysStore = defineStore('system', {
  state: (): SysState => ({
    userInfo: null,
    token: undefined,
    roleList: [],
    sessionTimeout: false,
    lastUpdateTime: 0,
    permissions: []
  }),

  getters: {
    getUserInfo(): Nullable<UserInfo> {
      return this.userInfo
    },
    getToken(): string {
      return this.token || getToken()
    },
    getRoleList(): [] {
      return this.roleList
    },
    getSessionTimeout(): boolean {
      return !!this.sessionTimeout
    },
    getLastUpdateTime(): number {
      return this.lastUpdateTime
    }
  },
  actions: {
    setToken(info: string | undefined) {
      this.token = info || '' // for null or undefined value
    },
    setRoleList(roleList) {
      this.roleList = roleList
    },
    setPermissions(permissionList) {
      this.permissions = permissionList
    },
    setUserInfo(info: UserInfo | null) {
      this.userInfo = info
      this.lastUpdateTime = new Date().getTime()
    },
    setSessionTimeout(flag: boolean) {
      this.sessionTimeout = flag
    },
    resetState() {
      this.userInfo = null
      this.token = ''
      this.roleList = []
      this.sessionTimeout = false
      removeToken()
    },

    async login(params) {
      try {
        const { token } = await LoginService(params)
        this.setToken(token)
        setToken(token)
        return this.afterLoginAction()
      } catch (error) {
        return Promise.reject(error)
      }
    },
    async updateRoutesList(roleRouters) {
      const permissionStore = usePermissionStore()
      await permissionStore.generateRoutes(roleRouters as AppCustomRouteRecordRaw[])

      permissionStore.getAddRouters.forEach((route) => {
        router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
      })
      permissionStore.setIsAddRouters(true)
    },
    async getRoutesListAction() {
      const roleRouters = await fetchRouterListService()
      await this.updateRoutesList(roleRouters)
      return roleRouters
    },

    async afterLoginAction(path = '/') {
      if (!this.getToken) return null
      const userInfo = await this.getUserInfoAction()

      const sessionTimeout = this.sessionTimeout
      if (sessionTimeout) {
        this.setSessionTimeout(false)
      } else {
        await this.getRoutesListAction()
        router.push(path)
      }
      return userInfo
    },
    updateUserInfo(userInfo: UserInfo) {
      const { roles = [], permissions = [] } = userInfo || {}
      if (Array.isArray(roles)) {
        const roleList = roles.map((item: RoleInfo) => item.value)
        this.setRoleList(roleList)
        this.setPermissions(permissions)
      } else {
        userInfo.roles = []
        this.setRoleList([])
        this.setPermissions([])
      }
      this.setUserInfo(userInfo)
    },
    async getUserInfoAction(): Promise<UserInfo | null> {
      if (!this.getToken) return null
      const userInfo = await fetchUserInfoService()
      this.updateUserInfo(userInfo)
      return userInfo
    },

    async logout() {
      if (this.getToken) {
        try {
          await logOutService()
        } catch {
          console.log('注销Token失败')
        }
      }
      this.setToken(undefined)
      removeToken()
      this.setSessionTimeout(false)
      this.setUserInfo(null)
      router.push('/app-login')
    },
    async bootStrap() {
      console.log('12323')
      const fetchUser = fetchUserInfoService()
      const fetchRouters = fetchRouterListService()
      const [user, routers] = await Promise.all([fetchUser, fetchRouters])

      this.updateUserInfo(user)
      this.updateRoutesList(routers)

      console.log('system boot', { user, routers })
    }
  }
})

export const useSysStoreWithOut = () => {
  return useSysStore(store)
}
